# C:/Python27/TextResuming/head_chunker.py
# This is main file
#

import model.Phrase.phrase_chunker as phraseChunker
import os
import types
from nltk.tree import Tree

class category:
	def __unicode__(self):
		return self.type
		
	def __init__(self, numField, type, direction, childs):
		self.numField = numField
		self.type = type
		self.direction = direction
		self.childs = childs

	def isChild(self, child):
		'''Checker whether a child is a categ s child '''
		return child in self.categ.childs

	def isLeftToRight(self):
		'''Checker whether a categ is left to right or not.'''
		return self.direction == 1


def isCategory(dictCategories, categ):
	'''Checker whether a categ is in dictCategories or not.'''
	return dictCategories.has_key(categ)

def readDataCategory(pathDataCategory):
	'''Read dataCategory from external file.'''
	try:
		fileInput = open(pathDataCategory)
		listCategory = fileInput.readlines()
		categories = []
		for categ in listCategory:
			if categ[-1] == '\n':
				categ = categ[:-1]
			categ = categ.split(',')
			categories.append(category(categ[0], categ[1], categ[2], categ[3:]))
		fileInput.close()
		return categories

	except Exception, e:
		print 'error readDataCategory', e
		return None

def createDictCategories(pathDataCategory):
	'''Create a dictionary contains data for categories.'''
	listCategory = readDataCategory(pathDataCategory)

	retval = dict()
	for categ in listCategory:
		retval[categ.type] = categ
	return retval

def getNextChild(parse_tree, direction, listCategory):
	'''Get a parse_tree that suitable for a listCategory.'''
	# direction : 0 = Left To Right, 1 = Right to Left
	buron = listCategory
	
	if direction == 0 or direction == '0':		
		# 0 = Left To Right
		i = 0
		found = False
		while (not found) and (i < len(parse_tree)):
			if(isinstance(parse_tree[i], list)):
				if (parse_tree[i].node in buron):
					found = True
				else:
					i += 1
			elif (isinstance(parse_tree[i], tuple)):
				if (parse_tree[i][1] in buron):
					found = True
				else:
					i += 1
			else:
				i += 1
		if found:
			# Jika ketemu, mengembalikan index anak parse_tree
			return i
		else :
			# Jika tidak ketemu, mengembalikan index yang out of bound
			return len(parse_tree) + 1
	elif direction == 1 or direction == '1':
		# 1 = Right to Left
		limit = -1 * len(parse_tree)
		i = -1
		found = False
		while (not found) and (i >= limit):
			if (isinstance(parse_tree[i], list)):
				if (parse_tree[i].node in buron):
					found = True
				else:
					i -= 1
			elif (isinstance(parse_tree[i], tuple)):
				if (parse_tree[i][1] in buron):
					found = True
				else:
					i -= 1
			else:
				i -= 1
		if found:
			# Jika ketemu, mengembalikan index anak parse_tree
			return i
		else :
			# Jika tidak ketemu, mengembalikan index yang out of bound
			return len(parse_tree) + 1
	else:
		return len(parse_tree) + 1

def head_chunk(dictCategories, parse_tree):
	'''Get a list of head tree'''
	# init retval as a list
	print parse_tree
	print '++++++++++++++++++++++++++++'

	retval = []
	if isinstance(parse_tree, tuple):
		debug('tuple')
		print parse_tree
		debug('tuple')
		#it is a tuple, leaves of a parse tree
		#retval.append(parse_tree)
		return parse_tree

	else:
		# a real parse tree
		# init a 
		if parse_tree.node == 'S':
			debug('S')
			# root dari parse tree, menunjukan awal, iterasi head_chunk untuk semua daun
			for child in parse_tree:
				#iterating through leaves
				retval.append(head_chunk(dictCategories, child))

		elif parse_tree.node == 'NP':
			#NP sector
			debug('NP')

			#init list for NP
			taggedPOS = []
			firstCase = ['NN', 'NNP', 'NNPS', 'NX', 'POS', 'JJR']
			secondCase = ['NP']
			thirdCase = ['$', 'ADJP', 'PRN']
			fourthCase = ['CD']
			fifthCase = ['JJ', 'JJS', 'RB', 'QP']

			print parse_tree[-1], 'parse_tree[-1]'
			if (isinstance(parse_tree[-1], tuple)):
				# If the last word is tagged POS, return (last-word);
				return (parse_tree[-1])
			
			else :
				# Else search from right to left for the first child which is an NN, NNP, NNPS, NNS, NX, POS, or JJR
				indexNextChild = getNextChild(parse_tree, 1, firstCase)
				if (indexNextChild != len(parse_tree) + 1):
					return (head_chunk(dictCategories, parse_tree[indexNextChild]))
				else :
					#Else search from left to right for first child which is an NP
					indexNextChild = getNextChild(parse_tree, 0, secondCase)
					if (indexNextChild != len(parse_tree) + 1):
						return (head_chunk(dictCategories, parse_tree[indexNextChild]))
					else:
						# Else search from right to left for the first child which is a $, ADJP or PRN
						indexNextChild = getNextChild(parse_tree, 1, thirdCase)
						if (indexNextChild != len(parse_tree) + 1):
							return (head_chunk(dictCategories, parse_tree[indexNextChild]))
						else:
							# Else search from right to left for the first child which is a CD
							indexNextChild = getNextChild(parse_tree, 1, fourthCase)
							if (indexNextChild != len(parse_tree) + 1):
								return (head_chunk(dictCategories, parse_tree[indexNextChild]))
							else :
								# Else search from right to left for the first child which is a JJ, JJS, RB or QP
								indexNextChild = getNextChild(parse_tree, 1, fifthCase)
								if (indexNextChild != len(parse_tree) + 1):
									return (head_chunk(dictCategories, parse_tree[indexNextChild]))
								else:
									# Else return the last word
									return (head_chunk(dictCategories, parse_tree[-1]))

		elif isCategory(dictCategories, parse_tree.node):
			debug('isCategory')
			#in the categories
			currentCategory = dictCategories[parse_tree.node]
			print 'currentCategory', currentCategory.type
			
			buron = currentCategory.childs
			direction = currentCategory.direction
			indexNextChild = getNextChild(parse_tree, direction, buron)

			if (indexNextChild == len(parse_tree) + 1):
				if direction == 1 or direction == '1':
					return (head_chunk(dictCategories, parse_tree[-1]))
				elif direction == 0 or direction == '0':
					return (head_chunk(dictCategories, parse_tree[0]))
				else:
					debug('None1')
					return None
			else:
				return (head_chunk(dictCategories, parse_tree[indexNextChild]))

		else:
			debug('None2')
			return (head_chunk(dictCategories, parse_tree[-1]))

	return retval

def getListPhrase(parse_tree, dictCategories):
	'''Return list of phrase from a parse_tree.

		Only phrase in dictCategories are returned.'''

	retval = []
	if (isinstance(parse_tree, Tree)):
		if (parse_tree.node == "S"):
			# Root of sentence
			for child in parse_tree:
				#iterating through leaves
				retval.extend(getListPhrase(child, dictCategories))

		elif (parse_tree.node == "NP"):
			# in dictionary
			retval.append(parse_tree)
			for child in parse_tree:
				#iterating through leaves
				retval.extend(getListPhrase(child, dictCategories))

		elif isCategory(dictCategories, parse_tree.node):
			# in dictionary
			retval.append(parse_tree)
			for child in parse_tree:
				#iterating through leaves
				retval.extend(getListPhrase(child, dictCategories))
		else:
			# Others
			pass

	return retval

def getHeadTreeOfPhrase(phrase, dictCategories):
	'''Return a head tree of a phrase.'''
	return [phrase.node,head_chunk(dictCategories, phrase)]

def getHeadTreeOfListOfPhrase(list_of_phrase, dictCategories):
	'''Return list of head tree from list_of_phrase'''
	retval = list()
	for phrase in list_of_phrase:
		retval.append(getHeadTreeOfPhrase(phrase, dictCategories))
	return retval

def debug(str):
	#print '=====', str, '=====\n'
	pass

def main():
	categories = readDataCategory('dataCategory.txt')
	for categ in categories:
		print categ.childs


if __name__ == '__main__':
	pathDataCategory = 'dataCategory.txt'
	#sentence = "Barack Obama said that he must improve this organization"
	sentence = "UK recession risk eases as service sector grows"
	#sentence = "As of September 14, Google Desktop will no longer be available for download, and existing installations will not be updated to include new features or fixes."
	
	dictCategories = createDictCategories(pathDataCategory)
	parse_tree = phraseChunker.chunkPhrase(phraseChunker.tagSentence(sentence))

	#retval = head_chunk(dictCategories, parse_tree)
	list_of_phrase =  getListPhrase(parse_tree, dictCategories)
	retval = getHeadTreeOfListOfPhrase(list_of_phrase, dictCategories)
	debug('retval')
	for phrase in list_of_phrase:
		print phrase
	print ('RETVAL')
	print retval


